#include<atomic>
#include<iostream>

template<typename T>
class shared_ptr {
private:
	struct Ref_Count {
		int count;
		Ref_Count(int c):count(c) {

		}
	};

public:
	shared_ptr(T* data):data_(data), ref_count_(new Ref_Count(1)){}
	shared_ptr(shared_ptr& sp):data_(sp.data_), ref_count_(sp.ref_count_) {
		++sp.ref_count_->count;
	}
	~shared_ptr() { deconstruct(); }

	shared_ptr& operator=(shared_ptr& sp) {
		if (sp.data_ == data_) return *this;
		deconstruct();
		ref_count_ =sp.ref_count_;
		++sp.ref_count_->count;
		data_ = sp.data_;
		return *this;
	}
	T& operator*() {
		return *data_;
	}
	T* operator->() {
		return data_;
	}
private:
	void deconstruct() {
		--ref_count_->count;
		if (ref_count_->count == 0) {
			if(data_!=NULL)
				delete data_;
			if(ref_count_!=NULL)
				delete ref_count_;
		}
	}

	T* data_;
	Ref_Count* ref_count_;
};

class Test {
public:
	Test() {
		std::cout << "Test()" << std::endl;
	}
	~Test() {
		std::cout << "~Test()" << std::endl;
	}
};

int main() {
	{
		shared_ptr<Test>sp1(new Test());
		shared_ptr<Test>sp2(new Test());
		sp1 = sp2;
		shared_ptr<Test>sp3 = sp1;
	}
	int i;
	std::cin >> i;
}